/*******************************************************************************
 * 版权：北京润尼尔网络科技有限公司，保留所有版权<br>
 * 版本：v1.0.0<br>
 * 文件：CompositeEditPart.js<br>
 * 日期：2016年9月20日<br>
 * 作者:王志远<br>
 * 功能：组合组件编辑件，作为MVC的Controller，传递Model和Figure操作<br>
 * 
 * 修改记录：<br>
 * 日期 描述 更新功能<br>
 ******************************************************************************/

window.makeNamespace(window, "Rainier.UI.V2");

/**
 * 类型名称：Rainier.UI.V2.CompositeEditPart<br>
 * 类型功能：组合组件编辑件<br>
 */
Rainier.UI.V2.CompositeEditPart = Rainier.UI.V2.AbstractEditPart.extend({

	NAME: "Rainier.UI.V2.CompositeEditPart",

	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.init<br>
	 * 函数功能：构造函数<br>
	 * 异常信息：无<br>
	 */
	init: function () {
		this._super();

		this.inputPortParts = new draw2d.util.ArrayList();
		this.outputPortParts = new draw2d.util.ArrayList();
		this.hybridPortParts = new draw2d.util.ArrayList();
		this.portParts = new draw2d.util.ArrayList();
		this.connectionParts = new draw2d.util.ArrayList();
	},

	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.createFigure<br>
	 * 函数功能：创建连接图元<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	createFigure: function () {
		var model = this.model;
		if (!this.figure) {
			var thisFigure = new draw2d.shape.basic.Rectangle(this.model.property.uiProperty);
			this.figure = thisFigure;
		}
		this.fillFigure();
		return this.figure;
	},

	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.refreshChildren<br>
	 * 函数功能：当删除或添加子模型、连接、端口时执行此函数，同步相应的Part和Figure<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	refreshChildren: function () {
		this.refreshPorts();
		this.refreshChildParts();
		this.refreshConnections();
		//this.refreshTransform();
	},


	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.autoRefreshChildren<br>
	 * 函数功能：当删除或添加子模型、连接、端口时执行此函数，同步相应的Part和Figure<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	autoRefreshChildren: function () {
		this.autoRefreshPorts();
		this.refreshChildParts();
		this.refreshConnections();
		//this.refreshTransform();
	},

	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.refreshChildParts<br>
	 * 函数功能：在model层添加了端口或删除了模型，执行这个函数可以同步相应的part和figure的添加或删除<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	refreshChildParts: function () {
		var models = this.model.getChildren();
		var parts = this.getChildren();
		var comPart = this;

		//没有删除也没有添加子模型
		if (models.length === parts.length) {
			return;
		}

		//添加了模型
		if (models.length > parts.length) {
			var isExisted = false;
			for (var i = 0; i < models.length; i++) {
				var model = models[i];
				for (var j = 0; j < parts.length; j++) {
					var part = parts[j];
					if (model === part.getModel()) {
						isExisted = true;
					}
				}

				if (!isExisted) {
					if (comPart.partFactory) {
						var childPart = comPart.partFactory.createObject(model);

						if (childPart) {
							childPart.setModel(model);
							childPart.setParent(comPart);

							var property = model.getProperty().modelProperty;
							if (!property.locator) {
								model.getProperty().modelProperty.locator =
									{ type: 'draw2d.layout.locator.CenterLocator', x: 0, y: 0 };
							}
							var locator = property.locator;
							if (locator) {
								var locator_type = locator.type;
								var locator_x = locator.x;
								var locator_y = locator.y;

								var _locator = null;
								if (locator_type !== "default") {
									_locator = eval("new " + locator_type + "()");
								} else {
									_locator = new Rainier.UI.V2.XYAbsFigureLocator();
								}
								if ((locator_type === 'draw2d.layout.locator.XYAbsPortLocator') ||
									(locator_type === 'draw2d.layout.locator.XYRelPortLocator' || (locator_type === 'default'))) {
									_locator.x = locator.x;
									_locator.y = locator.y;
								}
								var childFigure = childPart.createFigure();
								comPart.getFigure().add(childFigure, _locator);
								if (childFigure.updateDynamicSet) {
									childFigure.updateDynamicSet(true);
								}

								var transform = property.transform;
								if (transform && transform.angle != 0) {
									var command = new draw2d.command.CommandRotate(childFigure, transform.angle);
									//TODO:有个未查清BUG，180执行一次旋转，相当于执行90度，需执行两次才可以，这算神马。。。有时间再改吧
									if (transform.angle === 180) {
										command.execute();
									}
									command.execute();
								}

								comPart.addChild(childPart.getUuid(), childPart);
								childPart.refreshChildren();

								//添加事件侦听器
								var ctx = comPart.context;
								if (ctx) {
									var rootEditPart = ctx.rootEditPart;
									if (rootEditPart) {
										var listeners = rootEditPart.getModelEventListeners();
										if (listeners) {
											listeners.each(function (i, lis) {
												model.addPropertyChangeListener(lis.id, lis.listener);
											});
										}
									}
								}
							}
						}
					}
				}
				isExisted = false;
			}
		}

		//删除了子模型
		if (models.length < parts.length) {
			var delParts = new draw2d.util.ArrayList();
			for (var i = 0; i < parts.length; i++) {
				var isExisted = false;
				var part = parts[i];
				for (var j = 0; j < models.length; j++) {
					var model = models[j];
					if (model === part.getModel()) {
						isExisted = true;
					}
				}
				if (!isExisted) {
					delParts.add(part);
				}
			}

			delParts.each(function (i, part) {
				comPart.getFigure().remove(part.getFigure());
				comPart.removeChildById(part.getUuid());

				//添加事件侦听器
				part.getModel().removePropertyChangeListener(part.getUuid());
				part.unfillFigure();
				var ctx = comPart.context;
				if (ctx) {
					var rootEditPart = ctx.rootEditPart;
					if (rootEditPart) {
						var listeners = rootEditPart.getModelEventListeners();
						if (listeners) {
							listeners.each(function (i, lis) {
								part.getModel().removePropertyChangeListener(lis.id);
							});
						}
					}
				}
				part.refreshChildren();
			});
			return;
		}
	},


	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.refreshConnections<br>
	 * 函数功能：更新所有连接<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	refreshConnections: function () {
		if (this.model instanceof Rainier.UI.V2.CompositeModel) {
			var conns = this.model.getConnections();
			var connParts = this.connectionParts;
			var comPart = this;

			//没有删除也没有添加连接
			if (conns.getSize() === connParts.getSize()) {
				return;
			}

			//删除了连线
			if (conns.getSize() < connParts.getSize()) {
				var delParts = new draw2d.util.ArrayList();
				connParts.each(function (i, part) {
					var model = part.getModel();
					var isExisted = false;
					conns.each(function (j, conn) {
						if (conn === model) {
							isExisted = true;
						}
					});
					if (!isExisted) {
						delParts.add(part);
					}
				});
				isExisted = false;
				delParts.each(function (i, part) {
					comPart.getFigure().remove(part.getFigure());
					comPart.connectionParts.remove(part);

					//添加事件侦听器
					part.getModel().removePropertyChangeListener(part.getUuid());
					part.unfillFigure();
					var ctx = comPart.context;
					if (ctx) {
						var rootEditPart = ctx.rootEditPart;
						if (rootEditPart) {
							var listeners = rootEditPart.getModelEventListeners();
							if (listeners) {
								listeners.each(function (i, lis) {
									part.getModel().removePropertyChangeListener(lis.id);
								});
							}
						}
					}

				});
				return;
			}

			//添加了新的连接
			if (conns.getSize() > connParts.getSize()) {
				conns.each(function (i, conn) {

					var sourcePart = null;
					var targetPart = null;
					if (conn.__proto__.NAME == "Rainier.UI.V2.ConnectionModel") {
						var sourceModel = conn.getSourcePort();
						var targetModel = conn.getTargetPort();

						var comparePortpart = function (index, portpart) {
							var portModel = portpart.getModel();
							if (!sourcePart && portModel === sourceModel) {
								sourcePart = portpart;
							}
							if (!targetPart && portModel === targetModel) {
								targetPart = portpart;
							}
							if (sourcePart && targetPart) {
								return false;
							}
						};

						//搜索源和目标端口的编辑件
						Rainier.Basic.CompositeObject.recursiveEach(comPart, function (part) {

							if (part instanceof Rainier.UI.V2.CompositeEditPart) {
								var model = part.getModel();
								var inputparts = part.getInputParts();
								var outputparts = part.getOutputParts();
								var hybridparts = part.getHybridParts();
								var connsparts = part.getConnectionParts();

								inputparts.each(comparePortpart);

								outputparts.each(comparePortpart);

								hybridparts.each(comparePortpart);

								connsparts.each(function (i, connpart) {
									return Rainier.Basic.CompositeObject.recursiveEach(connpart, function (_part) {

										var __model = _part.getModel();
										var _hybridparts = _part.getHybridParts();
										_hybridparts.each(comparePortpart);

										if (sourcePart && targetPart) {
											return false;
										}
									});
								});

							}

							if (sourcePart && targetPart) {
								return false;
							}
						});

						if (!(sourcePart && targetPart)) {
							return false;
						}

						var isExisted = false;
						connParts.each(function (j, part) {
							if (part.getModel() === conn) {
								isExisted = true;
							}
						});

						if (!isExisted) {
							if (comPart.partFactory) {
								var connpart = comPart.partFactory.createObject(conn);
								if (connpart) {
									var portProperty = conn.getProperty().modelProperty;
									connpart.setModel(conn);
									connpart.setParent(comPart);
									
									var figure = connpart.createFigure(conn.label,conn);
									conn.label = figure.label.text;
									var canvas = null;

									if (comPart.getFigure() instanceof draw2d.Canvas) {
										canvas = comPart.getFigure();
									} else {
										canvas = comPart.getFigure().getCanvas();
									}

									figure.setSource(sourcePart.getFigure());
									figure.setTarget(targetPart.getFigure());
									canvas.add(figure);
									comPart.connectionParts.add(connpart);

									//添加事件侦听器
									var ctx = comPart.context;
									if (ctx) {
										var rootEditPart = ctx.rootEditPart;
										if (rootEditPart) {
											var listeners = rootEditPart.getModelEventListeners();
											if (listeners) {
												listeners.each(function (i, lis) {
													conn.addPropertyChangeListener(lis.id, lis.listener);
												});
											}
										}
									}
								}
							}
						}
						isExisted = false;
					}

				});
			}
		}
	},


	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.refreshPorts<br>
	 * 函数功能：更新输入、输出、混合端口，在model层添加了端口或删除了端口，执行这个函数可以同步相应的part和figure的添加或删除<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	refreshPorts: function () {
		if (this.model instanceof Rainier.UI.V2.CompositeModel) {
			var inputs = this.model.getInputPorts();
			var outputs = this.model.getOutputPorts();
			var hybrids = this.model.getHybridPorts();

			this.refreshPortModel(inputs, this.inputPortParts);
			this.refreshPortModel(outputs, this.outputPortParts);
			this.refreshPortModel(hybrids, this.hybridPortParts);

		}
	},

	refreshPortModel: function (portModels, portParts) {
		var comPart = this;

		//没有删除也没有添加端口
		if (portModels.getSize() !== portParts.getSize()) {

			//删除了端口
			if (portModels.getSize() < portParts.getSize()) {
				var delParts = new draw2d.util.ArrayList();
				portParts.each(function (i, part) {
					var model = part.getModel();
					var isExisted = false;
					portModels.each(function (j, port) {
						if (port === model) {
							isExisted = true;
						}
					});
					if (!isExisted) {
						delParts.add(part);
					}
					isExisted = false;
				});
				delParts.each(function (i, part) {
					part.getModel().removePropertyChangeListener(part.getUuid());
					comPart.getFigure().removePort(part.getFigure());
					portParts.remove(part);
				});
				return;
			}

			//添加了端口
			if (portModels.getSize() > portParts.getSize()) {
				portModels.each(function (i, port) {
					var isExisted = false;
					portParts.each(function (j, part) {
						if (part.getModel() === port) {
							isExisted = true;
						}
					});
					if (!isExisted) {
						if (comPart.partFactory) {
							var portpart = comPart.partFactory.createObject(port);
							if (portpart) {
								var portProperty = port.getProperty().modelProperty;
								var locator = portProperty.locator;
								if (locator) {
									var locator_type = locator.type;
									var portFigure = null;

									portpart.setModel(port);
									portpart.setParent(comPart);
									var _locator = null;
									if (locator_type !== "default") {
										_locator = eval("new " + locator_type + "()");
									} else {
										_locator = new Rainier.UI.V2.XYAbsFigureLocator();
									}
									if ((locator_type === 'draw2d.layout.locator.XYAbsPortLocator') ||
										(locator_type === 'draw2d.layout.locator.XYRelPortLocator') || (locator_type === 'default')) {
										_locator.x = locator.defaultX;
										_locator.y = locator.defaultY;
										portFigure = comPart.getFigure().createPort('hybrid', _locator);
										portFigure.attr(portpart.getModel().property.uiProperty);
										comPart.getFigure().layoutPorts();
										portpart.setFigure(portFigure);
									} else {
										portFigure = comPart.getFigure().createPort('hybrid', _locator);
										comPart.getFigure().layoutPorts();
										portpart.setFigure(portFigure);
									}
									portpart.getFigure().attr(portpart.getModel().property.uiProperty);
									portParts.add(portpart);
									comPart.getFigure().layoutPorts();
								}
							}
						}
					}
					isExisted = false;
				});
			}
		}
	},

	/**
	 * 函数名称：Rainier.UI.V2.CompositeEditPart.autoRefreshPorts<br>
	 * 函数功能：更新输入、输出、混合端口，在model层添加了端口或删除了端口，执行这个函数可以同步相应的part和figure的添加或删除<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	autoRefreshPorts: function () {
		if (this.model instanceof Rainier.UI.V2.CompositeModel) {
			var inputs = this.model.getInputPorts();
			var outputs = this.model.getOutputPorts();
			var hybrids = this.model.getHybridPorts();

			this.autoRefreshPortModel(inputs, this.inputPortParts);
			this.autoRefreshPortModel(outputs, this.outputPortParts);
			this.autoRefreshPortModel(hybrids, this.hybridPortParts);

		}
	},

	autoRefreshPortModel: function (portModels, portParts) {
		var comPart = this;

		//删除端口
		// if(portModels.getSize() == portParts.getSize()){
		// 	var delParts = new draw2d.util.ArrayList();
		// 	portParts.each(function(i,part){
		// 		var model = part.getModel();
		// 		var isExisted = false;
		// 		portModels.each(function(j,port){
		// 			if(port === model){
		// 				isExisted = true;
		// 			}
		// 		});
		// 		if(!isExisted){
		// 			delParts.add(part);
		// 		}
		// 		isExisted = false;
		// 	});
		// 	delParts.each(function(i,part){
		// 		part.getModel().removePropertyChangeListener(part.getUuid());
		// 		comPart.getFigure().removePort(part.getFigure());
		// 		portParts.remove(part);
		// 	});
		// 	return;
		// }

		//刷新端口
		if (portModels.getSize() == portParts.getSize()) {
			portModels.each(function (i, port) {
				var isExisted = false;
				port.removePropertyChangeListener(port.getUuid());
				// portParts.each(function(j,part){
				// if(part.getModel() === port){
				// console.log(part.getModel().getProperty().uiProperty.x);
				console.log(port.getProperty().uiProperty.x);
				// isExisted = true;
				// }
				// });
				if (!isExisted) {
					if (comPart.partFactory) {
						var portpart = comPart.partFactory.createObject(port);
						if (portpart) {
							var portProperty = port.getProperty().modelProperty;
							var locator = portProperty.locator;
							if (locator) {
								var locator_type = locator.type;
								var portFigure = null;

								portpart.setModel(port);
								portpart.setParent(comPart);
								var _locator = null;
								if (locator_type !== "default") {
									_locator = eval("new " + locator_type + "()");
								} else {
									_locator = new Rainier.UI.V2.XYAbsFigureLocator();
								}
								if ((locator_type === 'draw2d.layout.locator.XYAbsPortLocator') ||
									(locator_type === 'draw2d.layout.locator.XYRelPortLocator') || (locator_type === 'default')) {
									_locator.x = locator.defaultX;
									_locator.y = locator.defaultY;
									portFigure = comPart.getFigure().createPort('hybrid', _locator);
									portFigure.attr(portpart.getModel().property.uiProperty);
									comPart.getFigure().layoutPorts();
									portpart.setFigure(portFigure);
								} else {
									portFigure = comPart.getFigure().createPort('hybrid', _locator);
									comPart.getFigure().layoutPorts();
									portpart.setFigure(portFigure);
								}
								portpart.getFigure().attr(portpart.getModel().property.uiProperty);
								portParts.add(portpart);
								comPart.getFigure().layoutPorts();
							}
						}
					}
				}
				isExisted = false;
			});
		}
		// }
	},

	/**
	 * 函数名称：<br>
	 * 函数功能：<br>
	 * 参数输入：<br>
	 * 参数输出：<br>
	 * 函数返回：<br>
	 * 异常信息：<br>
	 */
	refreshTransform: function () {
		if (this.model instanceof Rainier.UI.V2.CompositeModel) {
			var pro = this.model.getProperty().modelProperty;
			if (pro) {
				var transform = pro.transform;
				if (transform.angle != 0) {
					var command = new draw2d.command.CommandRotate(this.figure, transform.angle);
					var canvas = null;

					if (this.getFigure() instanceof draw2d.Canvas) {
						canvas = this.getParent().getFigure();
					} else {
						canvas = this.getFigure().getCanvas();
					}
					canvas.getCommandStack().execute(command);
				}
			}
		}
	},

	/**
	 * 函数名称：Rainier.UI.V2.AbstractEditPart.handleModelEvent<br>
	 * 函数功能：处理模型事件<br>
	 * 参数输入：modelEvent:模型事件<br>
	 * 函数返回：无<br>
	 * 异常信息：无<br>
	 */
	handleModelEvent: function (modelEvent) {

		var eventName = modelEvent.getEventName();
		var oldValue = modelEvent.getOldValue();
		var newValue = modelEvent.getNewValue();

		//处理添加端口事件
		if ((eventName === Rainier.UI.V2.CompositeModel.MODEL_EVENT_ADD_PORT) ||
			(eventName === Rainier.UI.V2.CompositeModel.MODEL_EVENT_REMOVE_PORT) ||
			(eventName === Rainier.UI.V2.CompositeModel.MODEL_EVENT_ADD_CONNECTION) ||
			(eventName === Rainier.UI.V2.CompositeModel.MODEL_EVENT_REMOVE_CONNECTION) ||
			(eventName === Rainier.Basic.CompositeObject.SC_S_EVENT_ADD_CHILD) ||
			(eventName === Rainier.Basic.CompositeObject.SC_S_EVENT_REMOVE_CHILD)) {
			this.refreshChildren();
			return;
		}

		if (eventName === Rainier.UI.V2.CompositeModel.SC_S_EVENT_PARENT_CHANGED) {
			//nothing to do
			return;
		}

		this._super(modelEvent);
	},

	/**
	 * 函数名称：Rainier.UI.V2.AbstractEditPart.getInputParts<br>
	 * 函数功能：获取输入端口编辑件列表<br>
	 * 函数返回：draw2d.util.ArrayList<br>
	 * 异常信息：无<br>
	 */
	getInputParts: function () {
		return this.inputPortParts.clone();
	},

	/**
	 * 函数名称：Rainier.UI.V2.AbstractEditPart.getOutputParts<br>
	 * 函数功能：获取输出端口编辑件列表<br>
	 * 函数返回：draw2d.util.ArrayList<br>
	 * 异常信息：无<br>
	 */
	getOutputParts: function () {
		return this.outputPortParts.clone();
	},

	/**
	 * 函数名称：Rainier.UI.V2.AbstractEditPart.getHybridParts<br>
	 * 函数功能：获取混合端口编辑件列表<br>
	 * 函数返回：draw2d.util.ArrayList<br>
	 * 异常信息：无<br>
	 */
	getHybridParts: function () {
		return this.hybridPortParts.clone();
	},

	/**
	 * 函数名称：Rainier.UI.V2.AbstractEditPart.getConnectionParts<br>
	 * 函数功能：获取连接编辑件列表<br>
	 * 函数返回：draw2d.util.ArrayList<br>
	 * 异常信息：无<br>
	 */
	getConnectionParts: function () {
		return this.connectionParts.clone();
	}
});

